//
// Created by A on 2022/10/22.
//
#define _GNU_SOURCE // 只有定义这个宏才能使用clone

#include <stdio.h>
#include <malloc.h>

#include <sched.h>
#include <signal.h>

#include <sys/types.h>
#include <unistd.h>
#include "include/time_sched.h"

#define FIBER_STACK 8192

int pid;
struct data_t {
    int id;
};

struct data_t *data;


void clone_method();

void dt1();

void dt2();


int clone_routine(void *arg) {
    static pthread_mutex_t *lock_ptr;
    if (lock_ptr == NULL) {
        lock_ptr = malloc(sizeof(pthread_mutex_t));
        pthread_mutex_init(lock_ptr, NULL);
    }
    pthread_mutex_lock(lock_ptr);
    printf("now it`s %d\n", getpid());
    fflush(stdout);
    pthread_mutex_unlock(lock_ptr);
    struct itimerval value;
    value.it_value.tv_sec = 0;
    value.it_value.tv_usec = 100 * 1000; // 100ms
    value.it_interval.tv_sec = 1;
    value.it_interval.tv_usec = 0; // 1s
    pid = getpid();
    if (setitimer(ITIMER_REAL, &value, NULL) < 0) {
        perror("set timer error");
    }
    signal(SIGALRM, dt2);
    for (;;) {
        sleep(100000);
    };
}

void clone_method() {

    data = malloc(sizeof(struct data_t));
    int clone_flags = CLONE_VM;
    for (int i = 0; i < 5; i++) {
        void *stack = malloc(FIBER_STACK);
        clone(clone_routine,
              (char *) stack + FIBER_STACK,
              clone_flags,
              NULL);
    }
    for (;;) {
        sleep(12);
    };
}


void dt2() {
    static pthread_mutex_t *lock_ptr;
    if (lock_ptr == NULL) {
        lock_ptr = malloc(sizeof(pthread_mutex_t));
        pthread_mutex_init(lock_ptr, NULL);
    }
    static int v = 0;
    pthread_mutex_lock(lock_ptr);
    printf("I(%d)`ve change the pid into %d, v is %d\n", getpid(), pid, v++);
    printf("I read that data is %d,I(%d) change it to mine\n", data->id, getpid());
    data->id = getpid();
    pthread_mutex_unlock(lock_ptr);
}

void dt1() {
    static int v = 0;
    printf("dt11111111---%d\n", v++);
}

void do_timer2() {
    printf("doing the timer22222\n");
}


void *r1(void *arg) {
    printf("r1:cur pid:%d,cur tid:%ld\n", getpid(), gettid());
    struct itimerval value;
    value.it_value.tv_sec = 0;
    value.it_value.tv_usec = 100 * 1000; // 100ms
    value.it_interval.tv_sec = 1;
    value.it_interval.tv_usec = 0; // 1s
    if (setitimer(ITIMER_REAL, &value, NULL) < 0) {
        perror("set timer error");
    }
    signal(SIGALRM, dt1);
    for (;;) {}
    return NULL;
}

void *r2(void *arg) {
    printf("r2:cur pid:%d,cur tid:%ld\n", getpid(), gettid());
    struct itimerval value;
    value.it_value.tv_sec = 0;
    value.it_value.tv_usec = 100 * 1000; // 100ms
    value.it_interval.tv_sec = 3;
    value.it_interval.tv_usec = 0; // 300ms
    if (setitimer(ITIMER_REAL, &value, NULL) < 0) {
        perror("set timer error");
    }
    signal(SIGALRM, dt2);
    for (;;) {
        sleep(1000);
    }
    return NULL;
}

void test_timer() {
//    fork_method();
    clone_method();

}

void pthread_method() {
    struct itimerval value;
    value.it_value.tv_sec = 0;
    value.it_value.tv_usec = 100 * 1000; // 100ms
    value.it_interval.tv_sec = 1;
    value.it_interval.tv_usec = 0; // 1s
    pthread_t p1, p2;
    pthread_create(&p1, NULL, r1, NULL);
    pthread_create(&p2, NULL, r2, NULL);
    pthread_join(p1, NULL);
    pthread_join(p2, NULL);
}


